package org.vectrics.user.web.struts;

import java.util.Collection;
import java.util.Iterator;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.vectrics.SystemException;
import org.vectrics.common.http.HttpUtils;
import org.vectrics.domain.Domain;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.struts.VectricsActionData;
import org.vectrics.user.Person;
import org.vectrics.user.PersonPrivilegeGroup;
import org.vectrics.user.PersonPrivilegeGroupType;

public class UserGroupHelper {
    private transient final Logger log = Logger.getLogger(this.getClass());

    public String getSelectParameterName(PersonPrivilegeGroupType groupType) {
        String result = "";
        result += "grp_";
        result += groupType.getCode();
        return (result);
    }

    public String getHiddenParameterName(PersonPrivilegeGroupType groupType) {
        String result = "ent_";
        result += "grp_";
        result += groupType.getCode();
        return (result);
    }

    // Save the user groups.
    public void saveGroups(VectricsActionData actionData, Person person, Domain domain) {
        saveGroupsInternal(actionData, person, domain);
    }

    public void saveGroupsInternal(VectricsActionData actionData, Person person, Domain domain) {
        if (domain == null) {
            throw new SystemException("saveGroupsInternal() was passed a null domain");
        }

        HttpUtils.logRequestInfo(actionData.getRequest(), log, Level.INFO);

        if (log.isDebugEnabled()) {
            log.debug("Show person groups before save.");
            String message = "Before save, person=" + person.getName();
            Iterator personGroupIter = person.getPrivilegeGroups().iterator();
            while (personGroupIter.hasNext()) {
                PersonPrivilegeGroup group = (PersonPrivilegeGroup) personGroupIter.next();
                String doStr = "null";
                if (group.getDomain() != null)
                    doStr = group.getDomain().getDescription();
                message += "\r\n - group: " + group.getPersonPrivilegeGroupType().getCode() + "  Data Owner: " + doStr;
            }
            log.debug(message);
        }

        Iterator groupIter = CoreServiceLocator.getPersonService().findPrivilegeGroupTypes().iterator();
        while (groupIter.hasNext()) {
            PersonPrivilegeGroupType groupType = (PersonPrivilegeGroupType) groupIter.next();
            boolean requestHasPriv = requestRequiresGroupParamToBeEntered(actionData, groupType);
            if (requestHasPriv) {
                String selectedValue = this.findUserSelectionForGroup(actionData, groupType);
                if (selectedValue == null)
                    selectedValue = "none";

                if (log.isDebugEnabled()) {
                    log.debug("Submitted form requires group entry.  Group: " + groupType.getCode()
                            + "  User Selected: " + selectedValue);
                }

                // boolean userInGroup = false;
                PersonPrivilegeGroup prevGroup = person.findPrivilegeGroup(groupType, domain);

                if (log.isDebugEnabled()) {
                    log.debug("Group: " + groupType.getCode() + "  Prev Group: " + prevGroup);
                }

                if ((prevGroup == null) && (selectedValue.equals("none") == false)) {
                    log.info("Adding group for user. Group=" + groupType.getCode());
                    if (selectedValue.equals("global"))
                        person.addPrivilegeGroup(groupType, domain, true);
                    else
                        person.addPrivilegeGroup(groupType, domain, false);

                } else if ((prevGroup != null) && (selectedValue.equals("none") == true)) {
                    log.info("Removing group from person.  Group=" + groupType.getCode());
                    person.removePrivilegeGroup(groupType, domain);
                } else if ((prevGroup != null) && (prevGroup.getGlobal()) && (selectedValue.equals("domain"))) {
                    person.removePrivilegeGroup(groupType, domain);
                    person.addPrivilegeGroup(groupType, domain, false);
                } else if ((prevGroup != null) && (prevGroup.getGlobal() == false) && (selectedValue.equals("global"))) {
                    person.removePrivilegeGroup(groupType, domain);
                    person.addPrivilegeGroup(groupType, domain, true);
                } else {
                    log.debug("Group membership is same for user.  Group=" + groupType.getCode());
                }
            } else {
                log.debug("Submitted form does not allow entry group.  Group: " + groupType.getCode());
            }
        }
        groupIter = person.getPrivilegeGroups().iterator();
        while (groupIter.hasNext()) {
            PersonPrivilegeGroup personGroup = (PersonPrivilegeGroup) groupIter.next();
            if (personGroup.getDomain() == null)
                throw new SystemException("Dataowner for personGroup");
            CoreServiceLocator.getPersonService().addDefaultUserPrivileges(personGroup);
        }
        CoreServiceLocator.getPersonService().updatePerson(person);
        ThreadProperties.forcedCommit();
    }

    private String findUserSelectionForGroup(VectricsActionData actionData, PersonPrivilegeGroupType groupType) {
        String paramName = this.getSelectParameterName(groupType);
        String paramValue = actionData.getRequest().getParameter(paramName);
        return (paramValue);
    }

    private boolean requestRequiresGroupParamToBeEntered(VectricsActionData actionData,
            PersonPrivilegeGroupType groupType) {
        boolean result = false;
        String paramName = this.getHiddenParameterName(groupType);
        String paramValue = actionData.getRequest().getParameter(paramName);
        if ((paramValue != null) && (paramValue.length() > 0)) {
            result = true;
        }
        return (result);
    }

    public PersonPrivilegeGroup findGroup(PersonPrivilegeGroupType groupType, Domain domain, Collection personRoles) {
        PersonPrivilegeGroup found = null;
        Iterator iter = personRoles.iterator();
        while ((found == null) && (iter.hasNext())) {
            PersonPrivilegeGroup group = (PersonPrivilegeGroup) iter.next();
            if ((groupType.getCode().equals(group.getPersonPrivilegeGroupType().getCode()))
                    && (group.getDomain() != null) && (group.getDomain().getId().equals(domain.getId()))) {
                found = group;
            }
        }
        return (found);
    }

}
